﻿#ifndef PAI_H
#define PAI_H

#include "../Game/GameDefine.h"

#include "../_Global/GlobalClass.h"

#include <QObject>

//#include "_Global/UIGlobal.h"


//#include <QMessageBox>
//#include <QGraphicsSceneMouseEvent>

//#include <QPainter>
//#include <QGraphicsItem>
//#include <QPropertyAnimation>
//#include <QGraphicsItemAnimation>
//#include <QTimeLine>
//#include "GraphicsButton/GraphicsButton.h"

///////////////////////////////////////////////////////////////////


class _JiNeng
{
public:
    //技能类型
    enum _JiNengType
    {
        JiNengType_NULL = 0,
        JiNengType_PuTongJi,        //主动选择的普通技能(带次数限制)
        JiNengType_SuoDingJi,       //锁定(被动发动)
        JiNengType_JueXingJi,       //觉醒技
        JiNengType_ZhuGongJi,       //主公技
    };

    //技能值
    enum _JiNengValue
    {
        JiNengValue_NULL = 0,
        JiNengValue_GongJiJuLi = 1001,              //攻击距离加n!!
        JiNengValue_JiaJuLi,                        //加距离
        JiNengValue_JianJuLi,                       //减距离
        JiNengValue_TuoFu,                          //托福

        JiNengValue_ZuoYongLi = 2001,               //作用力
        JiNengValue_DaHangHaiShiDai,                //大航海时代
        JiNengValue_DuXiu,                          //独秀
        JiNengValue_ShenQu,                         //神曲
        JiNengValue_MengGuDiGuo,                    //连续杀
        JiNengValue_ZhanZhengZhiShen,               //战争之神
        JiNengValue_MengNaLiSha,                    //蒙娜丽莎
        JiNengValue_KaiSa,                          //凯撒
        JiNengValue_AYuWang,                        //阿育王
        JiNengValue_JunShiTanDing,                  //君士坦丁
    };

public:
    explicit _JiNeng(_JiNengValue v = JiNengValue_NULL, qint32 p1 = 0, qint32 p2 = 0):
        m_eJiNengValue(v),
        m_nJiNengParam(p1),
        m_nJiNengParam2(p2)
    {
        setProp(v);
    }
    virtual ~_JiNeng()
    {

    }

public:
    void setProp(_JiNengValue v)
    {
        switch(v)
        {
        case JiNengValue_ZuoYongLi:
        case JiNengValue_DaHangHaiShiDai:
        case JiNengValue_ShenQu:
        case JiNengValue_ZhanZhengZhiShen:
        case JiNengValue_MengNaLiSha:
        case JiNengValue_KaiSa:
            m_eJiNengType = JiNengType_PuTongJi;
            break;

        case JiNengValue_GongJiJuLi:
        case JiNengValue_JiaJuLi:
        case JiNengValue_JianJuLi:
        case JiNengValue_TuoFu:

        case JiNengValue_DuXiu:
        case JiNengValue_MengGuDiGuo:
        case JiNengValue_AYuWang:
            m_eJiNengType = JiNengType_SuoDingJi;
            break;

        default:
            m_eJiNengType = JiNengType_NULL;
        }
    }

    static QString getName(_JiNengValue value)
    {
        switch(value)
        {
        case JiNengValue_ZuoYongLi:
            return _T("作用力");
        case JiNengValue_DaHangHaiShiDai:
            return _T("大航海时代");
        case JiNengValue_DuXiu:
            return _T("独秀");
        case JiNengValue_ShenQu:
            return _T("神曲");
        case JiNengValue_MengGuDiGuo:
            return _T("蒙古帝国");
        case JiNengValue_ZhanZhengZhiShen:
            return _T("战争之神");
        case JiNengValue_MengNaLiSha:
            return _T("蒙娜丽莎");
        case JiNengValue_KaiSa:
            return _T("凯撒");
        case JiNengValue_AYuWang:
            return _T("阿育王");
        case JiNengValue_JunShiTanDing:
            return _T("君士坦丁");

        default:
            return _T("!神马技能?");
        }
    }
    QString getName()
    {
        return getName(m_eJiNengValue);
    }

public:
    //qint32 m_nID;       //目前无用
    _JiNengType     m_eJiNengType;
    _JiNengValue    m_eJiNengValue;

    qint32          m_nJiNengParam;     //目前次数(-1为无限)
    qint32          m_nJiNengParam2;    //次数上限

    static qint32   arrayTuoFuTime[5];
};


//所有牌的基类
class _BaseObject : public QObject
{
    Q_OBJECT
    Q_FLAGS(_Flags)
    Q_FLAGS(_Areas)
    Q_ENUMS(_ObjType)
    Q_ENUMS(_Area)
    //Q_ENUMS(Flag)

    Q_PROPERTY(qint32 id READ id WRITE setId)
    Q_PROPERTY(_ObjType objType READ objType)
    Q_PROPERTY(_Flags flags READ flags WRITE setFlags NOTIFY flagsChanged)
public:

    //属性数据:对象类型
    enum _ObjType {
        ObjType_NULL = 0,                  //无
        ObjType_Pai = 1,                   //牌
        ObjType_JiNeng = 2,                //技能
        ObjType_WuJiang = 4,               //武将
        ObjType_Player = 8,                //玩家
        ObjType_Button = 128,              //按钮
    };

    //游戏中使用:对象状态
    enum _Flag {
        Flag_Null = 0,          //无
        Flag_Enable = 1,        //亮色
        Flag_CanClicked = 2,    //可点
        Flag_Clicked = 4,       //已点

        //flag_ZhengMian = 4,     //正面
        //flag_Alpha = 8,        //半透明
        //flag_Show = 1,          //显示
    };
    Q_DECLARE_FLAGS(_Flags, _Flag)        //写在和E1同命名空间下(或同一类中)

    //设置状态时参数类型
    enum _FlagType {
        FlagType_Set,   //直接设置
        FlagType_Add,   //增加一或多
        FlagType_Clear, //清除一或多
    };


    //所有可 点击/放置 区域
    enum _Area {
        Area_Null = 0,
        Area_PaiDui = 1,   //牌堆
        Area_QiPaiDui = 2, //弃牌堆
        Area_ShouPai = 4,   //手牌区
        Area_PanDing = 8,   //判定区

        Area_WuQi = 16, //装备区
        Area_FangJu = 32, //装备区
        Area_JiaMa = 64, //装备区
        Area_JianMa = 128, //装备区
        Area_ZhuangBei = Area_WuQi | Area_FangJu | Area_JiaMa | Area_JianMa, //装备区

        Area_JiNeng = 256,   //技能

        Area_WuJiang = 512,   //武将区

        Area_Player = 1024,   //玩家区

        Area_Button = 2048,   //按钮
    };
    Q_DECLARE_FLAGS(_Areas, _Area)        //写在和E1同命名空间下(或同一类中)



public:
    //int changdu;    //长度
    explicit _BaseObject(QObject *parent = nullptr): QObject(parent)
    {
        setProp(-1, ObjType_NULL, Area_Null);
        init();
    }

    virtual ~_BaseObject()
    {
    }


signals:
    void flagsChanged(_Flags flags);

public:
    virtual void init()
    {
        clearSomeFlags(Flag_Null);
        m_bUsing = false;
    }

    //设置牌的类型和值
    Q_INVOKABLE void setProp(qint32 id = -1, _ObjType type = ObjType_NULL, _Area area = Area_Null)
    {
        m_nID = id;
        m_eObjType = type;
        m_eArea = area;
    }



    _BaseObject& operator=(_BaseObject& _t)
    {
        this->m_nID = _t.m_nID;
        this->m_eObjType = _t.m_eObjType;
        //this->eValue = _t.eValue;
        this->setFlags(_t.m_eFlags);
        this->m_eArea = _t.m_eArea;

        return *this;
    }




//property
    qint32 id() const
    {
        return m_nID;
    }

    void setId(qint32 &id)
    {
        m_nID = id;
    }


    _Flags flags() const
    {
        return m_eFlags;
    }

    void setFlags(_Flags flags)
    {
        if(m_eFlags != flags) {
            m_eFlags = flags;
            emit flagsChanged(m_eFlags);
            //qDebug()<<"flagsChanged send"<<m_eObjType<<m_nID<<m_eFlags;
        }
        else
        {
            //emit flagsChanged(m_eFlags);
            //qDebug()<<"flagsChanged send same"<<m_eObjType<<m_nID<<m_eFlags;
        }
    }

    void setFlags(_Flags flags,_FlagType type)
    {
        switch (type)
        {
        case FlagType_Set:
            setFlags(flags);
            break;
        case FlagType_Add:
            setSomeFlags(flags);
            break;
        case FlagType_Clear:
            clearSomeFlags(flags);
            break;
        default:
            break;
        }
    }

    void setSomeFlags(_Flags flags)
    {
        if((m_eFlags & flags) != flags)
        {
            m_eFlags |= flags;
            emit flagsChanged(m_eFlags);
            //qDebug()<<"flagsChanged send";
        }
        else
        {
            //qDebug()<<"flagAChanged send same"<<m_eObjType<<m_nID<<m_eFlags<<flags;
        }
    }
    void clearSomeFlags(_Flags flags)
    {
        if((m_eFlags & flags) != 0) {
            m_eFlags ^= flags;
            emit flagsChanged(m_eFlags);
            //qDebug()<<"flagsChanged send";
        }

        //m_eFlags &= ~flags;
    }

    _ObjType objType() const
    {
        return m_eObjType;
    }




public:
    bool        m_bUsing;       //是否使用

protected:
    qint32      m_nID;          //ID(下标),一个类型中唯一

    _ObjType    m_eObjType;     //类型
    _Flags      m_eFlags;       //状态
    _Area       m_eArea;        //区域


};


//牌
class _Pai : public _BaseObject
{
    Q_OBJECT
    Q_ENUMS(_PaiType)
    Q_ENUMS(_PaiValue)
    Q_PROPERTY(_PaiType type READ type)
    Q_PROPERTY(_PaiValue value READ value)
    Q_PROPERTY(_Area positionArea READ positionArea)
    Q_PROPERTY(qint32 positionValue READ positionValue)
    Q_PROPERTY(qint32 positionPlayer READ positionPlayer)
    Q_PROPERTY(QList<_JiNeng*> listJiNeng READ listJiNeng)

public:

    //牌的类型
    enum _PaiType
    {
        Type_All = -1,                  //所有
        Type_Null = 0,                  //无
        Type_JiBen = 1,                 //基本
        Type_FeiYanChiJingNang = 10,    //非延迟锦囊
        Type_YanChiJingNang = 11,       //延迟锦囊
        Type_WuQi = 20,                 //武器
        Type_FangJu = 21,               //防具
        Type_JiaMa = 22,                //+马
        Type_JianMa = 23,               //-马
        Type_JiNeng = 60,               //技能
    };

    //牌的值
    enum _PaiValue
    {
        Value_All = -1,         //所有扑克(不能修改这个了,有些作为下标)
        Value_Null = 0,         //没有扑克

        Value_Sha = 101,        //杀
        Value_Shan = 102,       //闪
        Value_Tao = 103,        //桃

        Value_Chai = 201,       //
        Value_Shun = 202,       //
        Value_WuZhong = 203,
        Value_JieDao = 204,
        Value_WanJian = 205,
        Value_NanMan = 206,
        Value_GaoKao = 207,

        Value_LeBuSiShu = 301,
        Value_ShanDian = 302,   //有 技能(属性为次数)

        Value_LianNu = 401,
        Value_ZhangBa = 402,
        Value_QingLong = 403,
        Value_GuanShiFu = 404,
        Value_HanBing = 405,
        Value_TanSu = 406,

        //技能
        Value_JiNeng_ZuoYongLi = 601,
        Value_JiNeng_DaHangHaiShiDai = 602,
        Value_JiNeng_DuXiu = 603,
        Value_JiNeng_ShenQu = 604,
        Value_JiNeng_MengGuDiGuo = 605,
        Value_JiNeng_ZhanZhengZhiShen = 606,
        Value_JiNeng_MengNaLiSha = 607,
        Value_JiNeng_KaiSa = 608,
        Value_JiNeng_AYuWang = 609,
        Value_JiNeng_JunShiTanDing = 610,
    };


public:
    explicit _Pai(QObject *parent = nullptr);
    virtual ~_Pai();

signals:
    void positionChanged();

public:
    _PaiType type() const
    {
        return m_ePaiType;
    }
    _PaiValue value() const
    {
        return m_ePaiValue;
    }
    _Area positionArea() const
    {
        return m_eArea;
    }
    qint32 positionValue() const
    {
        return m_nPositionValue;
    }
    qint32 positionPlayer() const
    {
        return m_nPositionPlayer;
    }

    QList<_JiNeng*> listJiNeng() const
    {
        return m_listJiNeng;
    }

public:
    virtual void init()
    {
        _BaseObject::init();
        setPosition(Area_Null,-1,-1);
        //m_bUsing = false;
    }

    Q_INVOKABLE void setProp(qint32 id,_PaiValue value)
    {
        _BaseObject::setProp(id, ObjType_Pai, Area_Null);

        //m_nID = id;
        clearAllJiNeng();
        m_ePaiValue = value;
        switch(value)
        {
        case _Pai::Value_Sha:
        case _Pai::Value_Shan:
        case _Pai::Value_Tao:
            m_ePaiType = _Pai::Type_JiBen;
            break;

        case _Pai::Value_Chai:
        case _Pai::Value_Shun:
        case _Pai::Value_WuZhong:
        case _Pai::Value_JieDao:
        case _Pai::Value_WanJian:
        case _Pai::Value_NanMan:
        case _Pai::Value_GaoKao:
            m_ePaiType = _Pai::Type_FeiYanChiJingNang;
            break;

        case _Pai::Value_ShanDian:
            m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_TuoFu,0,-1));
            m_ePaiType = _Pai::Type_YanChiJingNang;
            break;
        case _Pai::Value_LeBuSiShu:
            m_ePaiType = _Pai::Type_YanChiJingNang;
            break;

        case _Pai::Value_LianNu:
            m_ePaiType = _Pai::Type_WuQi;
            break;
        case _Pai::Value_ZhangBa:
        case _Pai::Value_QingLong:
            m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_GongJiJuLi,2));
            m_ePaiType = _Pai::Type_WuQi;
            break;
        case _Pai::Value_GuanShiFu:
        case _Pai::Value_HanBing:
        case _Pai::Value_TanSu:
            m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_GongJiJuLi,1));
            m_ePaiType = _Pai::Type_WuQi;
            break;
        default:
            m_ePaiType = _Pai::Type_Null;
        }
    }
    Q_INVOKABLE void setPosition(_Area area,qint32 value,qint32 player);
    Q_INVOKABLE static QString getName(_PaiValue v);
    Q_INVOKABLE QString getName(){return getName(static_cast<_PaiValue>(m_ePaiValue));}

    _Pai& operator=(_Pai& _t)
    {
        _BaseObject::operator =(_t);
        m_ePaiType = _t.m_ePaiType;
        m_ePaiValue = _t.m_ePaiValue;
        this->m_nPositionValue = _t.m_nPositionValue;
        this->m_nPositionPlayer = _t.m_nPositionPlayer;

        return *this;
    }

    static _Pai* createJiNengPai(_PaiValue jiNengValue)
    {
        _Pai *p = new _Pai;
        p->m_eObjType = ObjType_JiNeng;
        p->m_ePaiType = Type_JiNeng;
        p->m_ePaiValue = jiNengValue;
        p->m_eArea = Area_JiNeng;
        p->m_bUsing = true;

        _JiNeng *jn;
        switch(jiNengValue)
        {
        case Value_JiNeng_ZuoYongLi:
           p->m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_ZuoYongLi));
            break;
        case Value_JiNeng_DaHangHaiShiDai:
            p->m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_DaHangHaiShiDai));
            break;
        case Value_JiNeng_DuXiu:
            p->m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_DuXiu));
            break;
        case Value_JiNeng_ShenQu:
            p->m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_ShenQu));
            break;
        case Value_JiNeng_MengGuDiGuo:
            p->m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_MengGuDiGuo));
            break;
        case Value_JiNeng_ZhanZhengZhiShen:
            p->m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_ZhanZhengZhiShen));
            break;
        case Value_JiNeng_MengNaLiSha:
            p->m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_MengNaLiSha));
            break;
        case Value_JiNeng_KaiSa:
            jn = new _JiNeng(_JiNeng::JiNengValue_KaiSa);
            jn->m_nJiNengParam = 0;
            jn->m_nJiNengParam2 = 1;
            p->m_listJiNeng.append(jn);
            break;
        case Value_JiNeng_AYuWang:
            p->m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_AYuWang));
            break;
        case Value_JiNeng_JunShiTanDing:
            p->m_listJiNeng.append(new _JiNeng(_JiNeng::JiNengValue_JunShiTanDing));
            break;
        default:
            break;
        }
        return p;
    }

    bool containJiNeng(_JiNeng::_JiNengValue value)
    {
        QList<_JiNeng*>::const_iterator ii;
        for (ii = m_listJiNeng.constBegin(); ii != m_listJiNeng.constEnd(); ++ii)
        {
            _JiNeng *jineng = (_JiNeng *)(*ii);
            if(jineng->m_eJiNengValue == (_JiNeng::_JiNengValue)value)
                return true;
        }
        return false;
    }

    int getJiNengParam(_JiNeng::_JiNengValue value)
    {
        QList<_JiNeng*>::const_iterator ii;
        for (ii = m_listJiNeng.constBegin(); ii != m_listJiNeng.constEnd(); ++ii)
        {
            _JiNeng *jineng = (_JiNeng *)(*ii);
            if(jineng->m_eJiNengValue == (_JiNeng::_JiNengValue)value)
                return jineng->m_nJiNengParam;
        }
        return -1;
    }

    void clearAllJiNeng()
    {
        /*
        QObjectList::const_iterator ii;
        for (ii = m_listJiNeng.constBegin(); ii != m_listJiNeng.constEnd(); ++ii)
        {
               pGameCore->m_arrayPlayer[i].iJiaoSe = *ii;
        }*/
        qDeleteAll(m_listJiNeng);
        m_listJiNeng.clear();
    }

public:
    QList<_JiNeng*> m_listJiNeng;
    //int paifu;    //2副牌
    //int huase;    //花色,0=黑桃;1=红桃;2=草花;3=方片
    //int yanse;    //颜色
    //int dianshu;    //点数

protected:
//牌的类型和值
    _PaiType        m_ePaiType;
    _PaiValue       m_ePaiValue; //牌值
//牌所处的位置!!!
    //_Area           iPositionArea;      //区域
    qint32          m_nPositionValue;     //值
    qint32          m_nPositionPlayer;    //武将ID

};


class _WuJiang : public _BaseObject
{
    Q_OBJECT
    Q_ENUMS(_Value)
public:

    enum _Value {   //m_nID的值,必须从1开始(电脑选武将时要用!)
        Value_Null = 0,
        Value_LiLei = 1,
        Value_HanMeiMei,
        Value_NiuDun,
        Value_GeLunBu,
        Value_YaLiShanDa,
        Value_DanDing,
        Value_ChengJiSiHan,
        Value_NaPoLun,
        Value_DaFenQi,
        Value_KaiSa,
        Value_AYuWang,
        Value_ChengDuXiu,
    };


public:
    explicit _WuJiang(QObject *parent = nullptr);
    virtual ~_WuJiang();

public:
    Q_INVOKABLE _WuJiang::_Value setProp(_WuJiang::_Value v);

    virtual void init()
    {
        _BaseObject::init();
        //clearAllJiNeng();
        m_nID = Value_Null;
        //setMaxBloodCount(-1);
    }
    Q_INVOKABLE static QString getName(_WuJiang::_Value v);
    Q_INVOKABLE QString getName(){return getName(static_cast<_WuJiang::_Value>(m_nID));}

    void clearAllJiNeng()
    {
        /*
        QObjectList::const_iterator ii;
        for (ii = m_listJiNeng.constBegin(); ii != m_listJiNeng.constEnd(); ++ii)
        {
               pGameCore->m_arrayPlayer[i].iJiaoSe = *ii;
        }*/
        qDeleteAll(m_listJiNengPai);
        m_listJiNengPai.clear();
    }

    _WuJiang& operator=(_WuJiang& _t)
    {
        _BaseObject::operator =(_t);
        this->m_nMaxBloodCount = _t.m_nMaxBloodCount;

        return *this;
    }


public:
    qint32 maxBloodCount() const
    {
        return m_nMaxBloodCount;
    }
    void setMaxBloodCount(qint32 c)
    {
        m_nMaxBloodCount = c;
    }

public:
    QList<_Pai*> m_listJiNengPai;

protected:
    //Value eValue;
    qint32 m_nMaxBloodCount;
};


Q_DECLARE_METATYPE(_BaseObject*)
Q_DECLARE_METATYPE(_Pai*)
Q_DECLARE_METATYPE(_WuJiang*)
//Q_DECLARE_METATYPE(_BaseObject::_Flags)
Q_DECLARE_OPERATORS_FOR_FLAGS(_BaseObject::_Flags)  //写在全局
Q_DECLARE_OPERATORS_FOR_FLAGS(_BaseObject::_Areas)  //写在全局

#endif // PAI_H
